import { HttpService } from '@nestjs/axios';
import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';
import { ConfigService } from '@nestjs/config';
import { JwtService } from '@nestjs/jwt';
import { createWriteStream, writeFileSync, WriteStream } from 'fs';
import { join } from 'path';
import { Injectable, Logger, HttpStatus, HttpException } from '@nestjs/common';
import { OnlyofficeEditorConfig } from './config.default';
// import { IOnlyofficeCommand, IOnlyofficeForceSave } from './onlyoffice.interface';
import { firstValueFrom, lastValueFrom } from 'rxjs';
import { readFile, writeFile } from 'fs/promises';
import { Agent } from 'https';
import { defaultAxiosConfig } from 'src/common/utils';
import { Request } from 'express';
import { OnlyHttpService } from 'src/shared/only-http/only-http.service';
import * as dayjs from 'dayjs';
import { ApiPath } from 'src/common/api';
import { FileMangerService } from 'src/shared/file-manger/file-manger.service';

@Injectable()
export class OnlyofficeService {
  // requestNet: AxiosInstance;
  axiosConfig: AxiosRequestConfig;
  localPath: string;
  constructor(
    private readonly httpService: OnlyHttpService,
    private readonly config: ConfigService,
    private readonly jwt: JwtService,
    private readonly fileService: FileMangerService,
  ) {
    this.axiosConfig = defaultAxiosConfig;
  }
  localFilePath = (nameKey: string) => {
    const path = this.fileService.getLocalFilePath(nameKey);
    return path;
  };

  async callback(req: Request): Promise<any> {
    const { url, status, key, actions } = req.body || {};
    // debugger
    const callbackProcessSave = async () => {
      // Logger.log(status, headers, 'callback-body');
      if (!url) {
        return JSON.stringify({ error: 0 });
      }
      const fileData = await axios.get(url, { responseType: 'stream' });
      const pathName = this.localFilePath(key as string);
      Logger.log(pathName, 'pathName');
      return await writeFile(pathName, fileData.data);
    };

    if ([6].includes(status)) {
      try {
        await callbackProcessSave();
        const resToken = await this.httpService.get(ApiPath.ModuleLabGroup.GetCreateToken, {
          params: { user_no: actions?.[0]?.userid || '' },
        });
        const token = resToken.data?.AccessToken;
        const headers = { Authorization: 'Bearer ' + token };
        this.saveEditor(key, headers as any);
      } catch (error) {
        Logger.error(error, 'callback-error');
        return JSON.stringify({ error: 7 });
      }
    }
    return JSON.stringify({ error: 0 });
  }

  // 保存文档
  // async forceSave(body: any): Promise<any> {
  //   const { key, userdata, useJwtEncrypt } = body;
  //   let newBody: any = {
  //     c: 'forcesave',
  //     key,
  //     userdata,
  //   };
  //   // 如果是使用了 JWT 加密，重新组装请求参数
  //   if (useJwtEncrypt === 'y') {
  //     newBody = {
  //       token: this.jwt.sign(newBody, {
  //         secret: this.config.get('onlyoffice.secret'),
  //       }),
  //     };
  //   }
  //   const saveState = await this.httpService.axiosRef
  //     .post(this.config.get('onlyoffice.commandUrl'), newBody)
  //     .then((res) => res.data);

  //   // 组装返回值
  //   const data: any = {
  //     error: saveState.error,
  //     code: 602,
  //   };
  //   // 保存成功
  //   if (saveState.error === 0) {
  //     data.code = 0;
  //   } else if (saveState.error === 4) {
  //     // 文档未改变无需保存
  //     data.message = '文档未改变无需保存';
  //   } else {
  //     // 文档保存失败
  //     data.message = '文档保存失败';
  //   }
  //   return data;
  // }

  // 保存文档
  saveEditor = async (keyName: string, headers: Record<string, string>) => {
    // const baseUrl = this.config.get('API_HOST');
    const pathName = this.localFilePath(keyName);
    const fileData = await readFile(pathName);
    const fileDataBase64 = fileData.toString('base64');
    const headerIdRegex = /@file_id([^.]*)\./;
    const verIdRegex = /@ver_id([^.]*)\./;
    const headerId = keyName.match(headerIdRegex)?.[1] || '';
    const formVerId = keyName.match(verIdRegex)?.[1] || '';
    const fileNameSplit = keyName?.split('.');
    // debugger
    const fileDataKey =
      (parseInt(fileNameSplit?.[fileNameSplit.length - 2]) || dayjs().format('YYYYMMDDhhmmss')) + '.docx';

    const params = { HEADER_ID: headerId, FORM_VER_ID: formVerId, FILENAME: fileDataKey, BASE64STRING: fileDataBase64 };
    const resData = await this.httpService.post(ApiPath.Tim.SaveHeaderFile, params, {
      headers: headers,
      ...defaultAxiosConfig,
    });
    // Logger.log(resData.data, params, 'saveEditor');
    return resData;
  };

  // 编辑器默认配置
  editorDefaultConfig(): OnlyofficeEditorConfig {
    const defaultConfig = new OnlyofficeEditorConfig();
    return { ...defaultConfig };
  }

  // 以 JWT 加密方式签名编辑器配置
  signJwt(editorConfig: OnlyofficeEditorConfig): OnlyofficeEditorConfig {
    editorConfig.token = this.jwt.sign(editorConfig, {
      secret: this.config.get('onlyoffice.secret'),
    });
    return editorConfig;
  }
}
